package mop.model.resource;

import java.sql.Timestamp;
import java.text.DateFormat;

import mop.exception.IllegalReservationException;

/**
 * The class to keep track of a reservation
 * 
 * @invar	The start time should come before the end time
 *  		| isValidTimeCouple(start,end)
 *  
 * @author	MOP Team 7
 */
public class Reservation implements ReservationInterface
{

	/**
	 * Construct a reservation object
	 * 
	 * @param 	start
	 * 	 		The start time in timestamp format
	 * 
	 * @param 	end
	 *   		The end time in time stamp format
	 *   
	 * @throws 	IllegalReservationException
	 *  		if the start !< end
	 *  		|!isValidTimeCouple(start, end)
	 */
	public Reservation(Timestamp start, Timestamp end) 
		throws IllegalReservationException
	{
		if(!isValidTimeCouple(start, end))
		{
			throw new IllegalReservationException(start,end);
		}
		
		this.start = start;
		this.end = end;
	}
	
	/***************************************************************************
	 * 							Time
	 ***************************************************************************/
	
	/**
	 * @see ReservationInterface#getStart()
	 */
	public Timestamp getStart()
	{
		return this.start;
	}
	
	/**
	 * @see ReservationInterface#getEnd()
	 */
	public Timestamp getEnd()
	{
		return this.end;
	}
	
	/**
	 * Checks whether a combination of 2 timestamps can form a valid reservation.
	 * 
	 * @param 	start
	 * 			The start time
	 * 
	 * @param 	end
	 *  		The end time
	 *  
	 * @return 	if start < end return true, otherwise return false
	 */
	public static boolean isValidTimeCouple(Timestamp start, Timestamp end)
	{
		return start.before(end);
	}
	
	/**
	 * Checks whether the reservation is still valid.
	 * 
	 * @return	If the current time is larger than the end date,
	 * 			then this reservation is over.
	 */
	public boolean isDone()
	{
		Timestamp td = new Timestamp(System.currentTimeMillis());
		return td.after(this.end);
	}
	
	/**
	 * Checks whether the reservation is during the given time.
	 * 
	 * @param 	time
	 * 			A timestamp.
	 * 
	 * @pre		time is not null.
	 * 
	 * @return	True if the given time is "between" the time interval
	 * 			of the reservation. Otherwise false.
	 */
	public boolean isDuring(Timestamp time)
	{
		return start.before(time) && end.after(time);
	}
	
	/**
	 * Checks whether the reservation is during the given time period (start, end).
	 * 
	 * @param	start
	 * 			A time stamp.
	 * @param	end
	 * 			A time stamp.
	 * 
	 * @pre		start must be initialized.
	 * @pre		end must be initialized.
	 * @pre		end must be AFTER start!
	 * 
	 * @return	True if the given time period "falls somewhere in between" the time interval
	 * 			of the reservation. Otherwise false.
	 */
	public boolean isDuring(Timestamp start, Timestamp end)
	{
		// Ofwel ligt het start- of eindpunt in de reservatieperiode,
		// ofwel wordt de reservatieperiode overlapt door de gegeven periode.
		return ( this.isDuring(start) || this.isDuring(end) || 
				 (this.getStart().after(start) && this.getEnd().before(end)) );
	}
	
	/** 
	 * The start time.
	 */
	private Timestamp start;
	
	/**
	 * The end time.
	 */
	private Timestamp end;
	
	/**
	 * Returns a string representing this reservation.
	 * 
	 * @return A string representing this reservation.
	 */
	public String toString()
	{
            DateFormat format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
            StringBuffer buffer = new StringBuffer();
            buffer.append("From ");
            buffer.append(format.format(start));
            buffer.append(" till ");
            buffer.append(format.format(end));
            return buffer.toString();
	}
	
}